package com.example.controller;

import com.example.annotation.AuditLog;
import com.example.model.AuditLog.OperationType;
import com.example.model.AuditLog.RiskLevel;
import com.example.service.AuditLogService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Page;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 安全监控控制器
 */
@Slf4j
@RestController
@RequestMapping("/api/security/monitor")
@Tag(name = "安全监控", description = "安全监控和审计日志接口")
@RequiredArgsConstructor
@PreAuthorize("hasRole('ADMIN')")
public class SecurityMonitorController {

    private final AuditLogService auditLogService;

    @GetMapping("/audit-logs")
    @Operation(summary = "查询审计日志")
    @AuditLog(operation = OperationType.QUERY, module = "SECURITY", description = "查询审计日志")
    public ResponseEntity<Map<String, Object>> getAuditLogs(
            @RequestParam(required = false) String userId,
            @RequestParam(required = false) OperationType operationType,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime,
            @RequestParam(defaultValue = "0") int page,
            @RequestParam(defaultValue = "20") int size) {

        // 设置默认时间范围（最近7天）
        if (startTime == null) {
            startTime = LocalDateTime.now().minusDays(7);
        }
        if (endTime == null) {
            endTime = LocalDateTime.now();
        }

        Page<com.example.model.AuditLog> auditLogs = auditLogService.findAuditLogs(
                userId, operationType, startTime, endTime, page, size);

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("data", auditLogs.getContent());
        response.put("pagination", Map.of(
                "page", auditLogs.getNumber(),
                "size", auditLogs.getSize(),
                "totalElements", auditLogs.getTotalElements(),
                "totalPages", auditLogs.getTotalPages()
        ));

        return ResponseEntity.ok(response);
    }

    @GetMapping("/failed-operations")
    @Operation(summary = "查询失败操作")
    @AuditLog(operation = OperationType.QUERY, module = "SECURITY", description = "查询失败操作", riskLevel = RiskLevel.MEDIUM)
    public ResponseEntity<Map<String, Object>> getFailedOperations(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {

        if (startTime == null) {
            startTime = LocalDateTime.now().minusDays(1);
        }
        if (endTime == null) {
            endTime = LocalDateTime.now();
        }

        List<com.example.model.AuditLog> failedOperations = auditLogService.findFailedOperations(startTime, endTime);

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("data", failedOperations);
        response.put("count", failedOperations.size());

        return ResponseEntity.ok(response);
    }

    @GetMapping("/sensitive-operations")
    @Operation(summary = "查询敏感操作")
    @AuditLog(operation = OperationType.QUERY, module = "SECURITY", description = "查询敏感操作", riskLevel = RiskLevel.HIGH)
    public ResponseEntity<Map<String, Object>> getSensitiveOperations(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {

        if (startTime == null) {
            startTime = LocalDateTime.now().minusDays(1);
        }
        if (endTime == null) {
            endTime = LocalDateTime.now();
        }

        List<com.example.model.AuditLog> sensitiveOperations = auditLogService.findSensitiveOperations(startTime, endTime);

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("data", sensitiveOperations);
        response.put("count", sensitiveOperations.size());

        return ResponseEntity.ok(response);
    }

    @GetMapping("/operation-statistics")
    @Operation(summary = "操作统计")
    @AuditLog(operation = OperationType.QUERY, module = "SECURITY", description = "查询操作统计")
    public ResponseEntity<Map<String, Object>> getOperationStatistics(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime) {

        if (startTime == null) {
            startTime = LocalDateTime.now().minusDays(7);
        }
        if (endTime == null) {
            endTime = LocalDateTime.now();
        }

        Map<OperationType, Long> operationCounts = auditLogService.countOperationsByType(startTime, endTime);

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("data", operationCounts);
        response.put("timeRange", Map.of(
                "startTime", startTime,
                "endTime", endTime
        ));

        return ResponseEntity.ok(response);
    }

    @GetMapping("/security-dashboard")
    @Operation(summary = "安全仪表板")
    @AuditLog(operation = OperationType.QUERY, module = "SECURITY", description = "查询安全仪表板数据")
    public ResponseEntity<Map<String, Object>> getSecurityDashboard() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime last24Hours = now.minusDays(1);
        LocalDateTime last7Days = now.minusDays(7);

        // 最近24小时统计
        List<com.example.model.AuditLog> recentFailures = auditLogService.findFailedOperations(last24Hours, now);
        List<com.example.model.AuditLog> recentSensitive = auditLogService.findSensitiveOperations(last24Hours, now);

        // 最近7天统计
        Map<OperationType, Long> weeklyStats = auditLogService.countOperationsByType(last7Days, now);

        Map<String, Object> dashboard = new HashMap<>();
        dashboard.put("recentFailures", Map.of(
                "count", recentFailures.size(),
                "data", recentFailures.stream().limit(10).toList()
        ));
        dashboard.put("recentSensitiveOperations", Map.of(
                "count", recentSensitive.size(),
                "data", recentSensitive.stream().limit(10).toList()
        ));
        dashboard.put("weeklyStatistics", weeklyStats);
        dashboard.put("summary", Map.of(
                "totalFailures24h", recentFailures.size(),
                "totalSensitive24h", recentSensitive.size(),
                "totalOperations7d", weeklyStats.values().stream().mapToLong(Long::longValue).sum()
        ));

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("data", dashboard);

        return ResponseEntity.ok(response);
    }

    @PostMapping("/clean-logs")
    @Operation(summary = "清理过期日志")
    @AuditLog(operation = OperationType.DELETE, module = "SECURITY", description = "清理过期审计日志", riskLevel = RiskLevel.HIGH)
    public ResponseEntity<Map<String, Object>> cleanExpiredLogs(
            @RequestParam(defaultValue = "90") int retentionDays) {

        int deletedCount = auditLogService.cleanExpiredLogs(retentionDays);

        log.info("清理过期审计日志完成，删除记录数: {}, 保留天数: {}", deletedCount, retentionDays);

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", "清理完成");
        response.put("data", Map.of(
                "deletedCount", deletedCount,
                "retentionDays", retentionDays
        ));

        return ResponseEntity.ok(response);
    }

    @GetMapping("/security-alerts")
    @Operation(summary = "安全告警")
    @AuditLog(operation = OperationType.QUERY, module = "SECURITY", description = "查询安全告警")
    public ResponseEntity<Map<String, Object>> getSecurityAlerts() {
        LocalDateTime last24Hours = LocalDateTime.now().minusDays(1);
        LocalDateTime now = LocalDateTime.now();

        // 查询异常操作
        List<com.example.model.AuditLog> failedOperations = auditLogService.findFailedOperations(last24Hours, now);
        List<com.example.model.AuditLog> sensitiveOperations = auditLogService.findSensitiveOperations(last24Hours, now);

        // 生成告警
        List<Map<String, Object>> alerts = new java.util.ArrayList<>();

        // 失败操作告警
        if (failedOperations.size() > 10) {
            alerts.add(Map.of(
                    "type", "HIGH_FAILURE_RATE",
                    "level", "WARNING",
                    "message", "检测到异常高的操作失败率",
                    "count", failedOperations.size(),
                    "timeRange", "最近24小时"
            ));
        }

        // 敏感操作告警
        if (sensitiveOperations.size() > 5) {
            alerts.add(Map.of(
                    "type", "HIGH_SENSITIVE_OPERATIONS",
                    "level", "INFO",
                    "message", "检测到较多敏感操作",
                    "count", sensitiveOperations.size(),
                    "timeRange", "最近24小时"
            ));
        }

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("data", alerts);
        response.put("alertCount", alerts.size());

        return ResponseEntity.ok(response);
    }

    @GetMapping("/export")
    @Operation(summary = "导出审计日志")
    @AuditLog(operation = OperationType.EXPORT, module = "SECURITY", description = "导出审计日志", riskLevel = RiskLevel.MEDIUM)
    public ResponseEntity<Map<String, Object>> exportAuditLogs(
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime startTime,
            @RequestParam(required = false) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime endTime,
            @RequestParam(defaultValue = "csv") String format) {

        if (startTime == null) {
            startTime = LocalDateTime.now().minusDays(7);
        }
        if (endTime == null) {
            endTime = LocalDateTime.now();
        }

        // 这里应该实现实际的导出逻辑
        // 为了演示，只返回导出任务信息
        String exportId = java.util.UUID.randomUUID().toString();

        Map<String, Object> response = new HashMap<>();
        response.put("success", true);
        response.put("message", "导出任务已创建");
        response.put("data", Map.of(
                "exportId", exportId,
                "format", format,
                "startTime", startTime,
                "endTime", endTime,
                "status", "PROCESSING"
        ));

        return ResponseEntity.ok(response);
    }
}
